// services/order.service.js
const {Order, OrderReply, OrderAttachment, OrderStatusLog } = require('../model/Order');
const User = require('../model/User');
const Advisor = require('../model/Advisor');
const Service = require('../model/Service')

const { Op } = require('sequelize');
const ApiError = require('../tool/utils/api_error');
const {ORDER_STATUS, LEDGER_BIZ} = require('../model/other/enums');
const { addHours, addMinute, isAllowedFileType} = require('../tool/function');
const {sequelize} = require("../config/mysql_config");
const {scheduleOrderDeadlines} = require("./order_monitor_service");
const {addLedger} = require("./coin_ledger");



/** 写状态日志 */
async function addStatusLog(t, { orderId, fromStatus, toStatus, reasonCode }) {
    await OrderStatusLog.create(
        { orderId, fromStatus, toStatus, reasonCode },
        { transaction: t }
    );
}

/** 3.1 用户创建订单 */
async function createOrderService({
                                      userId,
                                      advisorId,
                                      serviceId,
                                      generalSituation = null,
                                      specificQuestion = null,
                                      isRush = 0,
                                      attachmentList = [],
                                  }) {
    return await sequelize.transaction(async (t) => {
        // 1) 获取用户并加锁
        const user = await User.findByPk(userId, { transaction: t, lock: t.LOCK.UPDATE });
        if (!user) throw ApiError.BadRequest('用户不存在');
        const userCoin = Number(user.coin || 0);

        // 2) 获取服务信息
        const svc = await Service.findOne({
            where: {id: serviceId, advisorId: advisorId}
        });
        if (!svc) throw ApiError.BadRequest('该顾问不存在该服务');

        const serviceType = svc.serviceType;
        const serviceName = svc.serviceName || svc.name || '';
        const servicePriceCoin = Math.round(Number(svc.price) * 100); // $→coin
        const rushPrice = isRush ? Math.floor(servicePriceCoin / 2) : 0;
        const totalPrice = servicePriceCoin + rushPrice;

        if (totalPrice > userCoin) {
            throw ApiError.BadRequest('余额不足');
        }

        // 3) 时间字段
        const paidAt = new Date();
        const rushDeadlineAt = isRush ? addMinute(paidAt, 1) : null;
        const expireAt = addMinute(paidAt, 2);

        // 4) 创建订单
        const order = await Order.create(
            {
                userId,
                advisorId,
                serviceId,
                status: ORDER_STATUS.PENDING,
                isRush: isRush ? 1 : 0,
                isRushCanceled: 0,
                rushPrice,
                servicePrice: servicePriceCoin,
                totalPrice,
                paidAt,
                repliedAt: null,
                completedAt: null,
                rushDeadlineAt,
                expireAt,
                generalSituation,
                specificQuestion,
                attachmentsCnt: Math.min(attachmentList.length || 0, 20),
                serviceType,
                serviceName,
            },
            { transaction: t }
        );

        // 5) 附件写入
        for (const it of (attachmentList || [])) {
            const { fileUrl, fileType, fileName } = it || {};
            if (!isAllowedFileType(fileType)) {
                throw ApiError.BadRequest(`附件${fileName}类型错误，请重新上传附件`);
            }
            await OrderAttachment.create(
                {
                    orderId: order.id,
                    uploaderId: userId,
                    fileUrl,
                    fileType,
                },
                { transaction: t }
            );
        }

        // 6) 扣减用户余额 + 记账
        const newCoin = userCoin - totalPrice;
        await user.update({ coin: newCoin }, { transaction: t });
        await addLedger(t, {
            accountType: 'user',
            accountId: userId,
            orderId: order.id,
            bizType: LEDGER_BIZ.ORDER_PAY_SERVICE,
            amount: -totalPrice,
            balanceAfter: newCoin,
        });

        //  7) 更新顾问历史订单数 +1（加锁保证并发安全）
        const advisor = await Advisor.findByPk(advisorId, { transaction: t, lock: t.LOCK.UPDATE });
        if (!advisor) throw ApiError.BadRequest('顾问不存在');
        const newTotalOrderCnt = Number(advisor.totalOrderCnt || 0) + 1;
        await advisor.update({ totalOrderCnt: newTotalOrderCnt }, { transaction: t });

        // 8) 写入 Redis ZSET 用于监控超时
        await scheduleOrderDeadlines({
            orderId: order.id,
            expireAt,
            rushDeadlineAt,
            isRush: !!isRush,
        });

        return order;
    });
}

/** 3.2 用户订单列表 */
async function getUserOrdersService({ userId, pageSize = 10, offset = 0 }) {
    /*订单列表：[
        顾问ID，
        顾问名称 userName,(通过顾问ID在顾问表中查）
        specificQuestion,
        订单支付时间paidAt
        服务类型serviceType，
        订单状态status，
        ]
        常见分页字段
    */
    const { rows, count } = await Order.findAndCountAll({
        where: { userId },
        order: [['createdAt', 'DESC']],
        limit: pageSize,
        offset,
        attributes: ['id', 'advisorId', 'specificQuestion', 'paidAt', 'status', 'serviceId'],
    });

    // 批量取顾问名称
    const advisorIds = rows.map(r => r.advisorId);
    const advisors = await Advisor.findAll({
        where: { id: { [Op.in]: advisorIds } },
        attributes: ['id', 'userName'],
    });
    const advisorMap = new Map(advisors.map(a => [a.id, a.userName]));

    const list = rows.map(r => ({
        orderId: r.id,
        advisorId: r.advisorId,
        advisorName: advisorMap.get(r.advisorId) || null,
        specificQuestion: r.specificQuestion,
        paidAt: r.paidAt,
        serviceType: r.serviceType,
        status: r.status,
    }));

    return { count, list, pageSize, offset };
}

/** 3.3 用户订单详情 */
async function getOrderDetailService({ userId, orderId }) {
    const order = await Order.findOne({
        where: { id: orderId, userId },
    });
    if (!order) throw ApiError.NotFound('订单不存在');

    const attachments = await OrderAttachment.findAll({
        where: { orderId },
        attributes: ['id', 'fileUrl', 'fileType', 'createdAt'],
    });

    const advisor = await Advisor.findByPk(order.advisorId, { raw: true, attributes: ['id', 'userName'] });

    const orderPlain = order.get({plain: true, getters: true})
    const result = {
        ...orderPlain,
        attachments,
        advisorName: advisor ? advisor.userName : null,
    };

    if (order.status === ORDER_STATUS.COMPLETED) {
        result.replies = await OrderReply.findAll({
            where: {orderId},
            order: [['createdAt', 'ASC']],
        });
    }

    return result;
}

/** 3.4 顾问回复订单 */
async function advisorReplyOrderService({ advisorId, orderId, replyType, replyMessage, replyAudioUrl }) {
    return await sequelize.transaction(async (t) => {
        // 1) 锁订单，避免与超时并发
        const order = await Order.findOne({
            where: { id: orderId, advisorId },
            transaction: t,
            lock: t.LOCK.UPDATE,
        });
        if (!order) throw ApiError.NotFound('订单不存在或不属于该顾问');
        if (order.status !== ORDER_STATUS.PENDING) {
            throw ApiError.BadRequest('订单状态不可回复');
        }

        // 2) 锁顾问行
        const adv = await Advisor.findByPk(advisorId, { transaction: t, lock: t.LOCK.UPDATE });
        if (!adv) throw ApiError.BadRequest('顾问不存在');

        // 3) 写回复
        if (replyType === 'text') {
            const textCnt = (replyMessage || '').length;
            await OrderReply.create(
                { orderId, advisorId, contentType: 'text', contentText: replyMessage, textCnt },
                { transaction: t }
            );
        } else {
            await OrderReply.create(
                { orderId, advisorId, contentType: 'audio', audioUrl: replyAudioUrl },
                { transaction: t }
            );
        }

        // 4) 订单完成
        const now = new Date();
        const from = order.status;
        await order.update(
            { status: ORDER_STATUS.COMPLETED, repliedAt: now, completedAt: now },
            { transaction: t }
        );
        await addStatusLog(t, {
            orderId,
            fromStatus: from,
            toStatus: ORDER_STATUS.COMPLETED,
            reasonCode: 'ADVISOR_REPLY'
        });

        // 5) 顾问入账
        const total = Number(order.totalPrice || 0);
        const advCoin = Number(adv.coin || 0) + total;
        await adv.update({ coin: advCoin }, { transaction: t });
        await addLedger(t, {
            accountType: 'advisor',
            accountId: advisorId,
            orderId,
            bizType: LEDGER_BIZ.ORDER_ADVISOR_INCOME,
            amount: total,
            balanceAfter: advCoin,
        });

        //  6) 已完成订单数 +1（原子自增；不需要先查出旧值）
        await Advisor.update(
            { completedOrderCnt: sequelize.literal('completed_order_cnt + 1') },
            { where: { id: advisorId }, transaction: t }
        );
    });
}
module.exports = {
    createOrderService,
    getUserOrdersService,
    getOrderDetailService,
    advisorReplyOrderService,
};